/*
    UUID字符串生成
    * UUID的标准型式包含32个16进制数字字符，以连字号分为五段，形式为8-4-4-4-12的32个16进制字符
    * 这里采用8个1字节随机数 + 一个8字节序号来生成UUID
*/
#include "uuid.h"

#include <atomic>
#include <iomanip>
#include <random>
#include <sstream>

namespace chat {
std::string Uuid::uuid() {  // UUID: 8-4-4-4-12的32个16进制数

    std::stringstream ss;  // 用于存放uuid的字符流

    // 1. 创建一个机器随机数对象
    std::random_device rd;
    // 2. 将机器随机数作为种子，生成伪随机对象
    std::mt19937 genenrator(rd());
    // 3. 限制随机数范围 [0, 255]
    std::uniform_int_distribution<int> distibution(0, 255);

    // 随机生成8个16进制随机数 num1num2num3num4-num5num6-num7num8
    for (int i = 0; i < 8; i++) {
        if (i == 4 || i == 6) ss << '-';
        ss << std::setw(2) << std::setfill('0') << std::hex
           << distibution(genenrator);
    }

    ss << '-';

    static std::atomic<size_t> seq(1);  // 序号，每次加一
    size_t cur = seq.fetch_add(1);      // 原子操作，保证线程安全

    // 还剩8个字节，每次取前1个字节（8位）
    for (int i = 7; i >= 0; --i) {
        if (i == 5) ss << '-';
        ss << std::setw(2) << std::setfill('0') << std::hex
           << ((cur >> (i * 8)) & 0xff);
    }

    return ss.str();
}
}  // namespace chat